import base64
import json
import pickle
from datetime import datetime

from django_redis import get_redis_connection

from meiduo_mall.utils import constants
from meiduo_mall.utils.my_loginview import LoginreqyiredView
from django import http
from django.core.paginator import Paginator
from django.shortcuts import render
from django.views import View

from goods.models import SKU, GoodsCategory, CategoryVisitCount
from meiduo_mall.utils.my_category import get_categories
from meiduo_mall.utils.response_code import RET


class ListView(View):
    def get(self, request, category_id, page):
        """

        :param request:
        :param category_id:
        :param page:
        :return:
        """
        # 获取参数
        sort = request.GET.get("sort", "default")
        # 根据sort 设置数据中查询的排序字段
        if sort == "price":
            sort_filed = "-price"  # 按照价格降序排序
        elif sort == "hot":
            sort_filed = "-sales"  # 按照销量降序排序
        else:
            sort_filed = "create_time"  # 按照创建时间升序排序

        # 获取分类数据
        categories = get_categories()
        # 查询skus数据
        skus = SKU.objects.filter(category_id=category_id).order_by(sort_filed).all()
        # 获取分类队对象
        paginator = Paginator(skus, 5)
        paginate = paginator.page(page)
        skus_list = paginate.object_list  # 当前页对象列表
        current_page = paginate.number  # 当前页
        total_page = paginator.num_pages  # 总页数
        category = GoodsCategory.objects.get(id=category_id)  # 获取三级分类 为做面包屑导航

        context = {
            'categories': categories,
            'skus': skus_list,
            'category': category,
            "current_page": current_page,
            "total_page": total_page,
            "sort": sort,
            # "username": request.user.username

        }
        return render(request, 'list.html', context=context)


class HotSkuView(View):
    def get(self, request, category_id):
        # 根据分类编号获取skus数据
        skus = SKU.objects.filter(category_id=category_id).all()[:3]

        # 拼接数据
        hot_sku_list = []
        for sku in skus:
            sku_dict = {
                "image_url": sku.default_image_url.url,
                "name": sku.name,
                "price": sku.price,
                'id':sku.id
            }
            hot_sku_list.append(sku_dict)

        return http.JsonResponse({"hot_sku_list": hot_sku_list})


class SKUDetailView(View):
    def get(self, request, sku_id):
        # 查询商品分类
        categories = get_categories()

        # 获取面包屑数据
        sku = SKU.objects.get(id=sku_id)  # 获取当前浏览的商品对象
        category = sku.category  # 三级分类

        # 规格信息数据
        sku_specs = sku.specs.order_by('spec_id')  # 查询SKU具体规格  苹果iphoneX手机的所有规格
        sku_key = []
        for spec in sku_specs:  # 遍历iphoneX手机的所有规格添加到列表中
            sku_key.append(spec.option.id)
        # 获取商品的所有SKU
        skus = sku.spu.sku_set.all()  # 获取
        # 构建不同规格参数（选项）的sku字典
        spec_sku_map = {}
        for s in skus:
            # 获取sku的规格参数
            s_specs = s.specs.order_by('spec_id')
            # 用于形成规格参数-sku字典的键
            key = []
            for spec in s_specs:
                key.append(spec.option.id)
            # 像规格参数-sku字典添加记录
            spec_sku_map[tuple(key)] = s.id
        good_specs = sku.spu.specs.order_by('id')
        # 若当前sku的规格信息不完整，则不再继续
        if len(sku_key) < len(good_specs):
            return
        for index, spec in enumerate(good_specs):
            # 复制当前sku的规格键
            key = sku_key[:]
            # 该规格的选项
            spec_options = spec.options.all()
            for option in spec_options:
                # 在规格参数sku字典中查找符合当前规格的sku
                key[index] = option.id
                option.sku_id = spec_sku_map.get(tuple(key))
            spec.spec_options = spec_options

        # 拼接数据，渲染页面
        context = {
            "categories": categories,
            "category": category,
            "sku": sku,
            "specs": good_specs,
            "username": request.user.username
        }
        return render(request, 'detail.html', context=context)


class CategoryVisitCountView(View):
    def post(self, request, category_id):
        today = datetime.today()

        try:
            # 这一句的意思是：查找当天 这个三级分类有没有被访问过
            category_visit = CategoryVisitCount.objects.get(date=today, category_id=category_id)
        except Exception as e:
            # 如果没有则创建当天浏览次数的对象
            category_visit = CategoryVisitCount()
            # 设置当天事件数据
            category_visit.date = today
            # 设置访问三级分类id
            category_visit.category_id = category_id

        category_visit.count += 1
        category_visit.save()

        return http.JsonResponse({"code": RET.OK}, status=200)


class BrowseHistoryView(LoginreqyiredView):
    def post(self, request):
        # 获取参数
        dict_data = json.loads(request.body.decode())
        sku_id = dict_data.get("sku_id")  # 前端带过来的
        user = request.user

        # 校验参数
        if not sku_id:
            return http.JsonResponse({"code": RET.PARAMERR, "errmsg": "参数不全"})

        # 数据入库（去重， 删除sku_id历史）
        redis_conn = get_redis_connection("history")
        redis_conn.lrem("history_%s" % user.id, 0, sku_id)  # 如果与相同的sku_id 就删除 就是相同的记录

        # 添加用户浏览商品到历史记录
        redis_conn.lpush("history_%s" % user.id, sku_id)
        # 截图保证只有五条记录
        redis_conn.ltrim("history_%s" % user.id, 0, 4)
        return http.JsonResponse({'coded': RET.OK, 'errmsg': "操作成功"})

    def get(self, request):
        # 获取五条浏览器记录
        redis_conn = get_redis_connection("history")
        # 获取redis里面商品sku的id  就是user.id对应的值  user.id是键
        sku_ids = redis_conn.lrange("history_%s" % request.user.id, 0, -1)

        # 数据拼接
        sku_list = []
        for sku_id in sku_ids:
            sku = SKU.objects.get(id=sku_id)
            sku_dict = {
                'id': sku.id,
                'default_image_url': sku.default_image_url.url,
                'name': sku.name,
                'price': sku.price
            }
            sku_list.append(sku_dict)

        return http.JsonResponse({'code': RET.OK, 'skus': sku_list})


# Create your views here.
